Shiny is an R package that makes it easy to build interactive web applications (apps) straight from R. This lesson will get you started building Shiny apps right away.
If you still haven't installed the Shiny package, open an R session, connect to the internet, and run
The Shiny package has eleven built-in examples that each demonstrate how Shiny works. Each example is a self-contained Shiny app.
The Hello Shiny example plots a histogram of R's faithful
dataset with a configurable number of bins. Users can change the number of bins with a slider bar, and the app will immediately respond to their input. You'll use Hello Shiny to explore the structure of a Shiny app and to create your first app.
To run Hello Shiny, type:
Shiny apps are contained in a single script called app.R
. The script app.R
lives in a directory (for example, newdir/
) and the app can be run with runApp("newdir")
.
app.R
has three components:
a user interface object
a server function
a call to the shinyApp
function
The user interface (ui
) object controls the layout and appearance of your app. The server
function contains the instructions that your computer needs to build your app. Finally the shinyApp
function creates Shiny app objects from an explicit UI/server pair.
Note: Prior to version 0.10.2, Shiny did not support single-file apps and the ui
object and server
function needed to be contained in separate scripts called ui.R
and server.R
, respectively. This functionality is still supported in Shiny, however the tutorial and much of the supporting documentation focus on single-file apps.
One nice feature about single-file apps is that you can copy and paste the entire app into the R console, which makes it easy to quickly share code for others to experiment with. For example, if you copy and paste the code above into the R command line, it will start a Shiny app.
Here is the ui
object for the Hello Shiny example.
Here is the server
function for the Hello Shiny example.
At one level, the Hello Shiny server
function is very simple. The script does some calculations and then plots a histogram with the requested number of bins.
However, you'll also notice that most of the script is wrapped in a call to renderPlot
. The comment above the function explains a bit about this, but if you find it confusing, don't worry. We'll cover this concept in much more detail soon.
Play with the Hello Shiny app and review the source code. Try to develop a feel for how the app works. But before you do so, note that in your app.R
file you will need to start with loading the Shiny package and end with a call to shinyApp
:
Your R session will be busy while the Hello Shiny app is active, so you will not be able to run any R commands. R is monitoring the app and executing the app's reactions. To get your R session back, hit escape or click the stop sign icon (found in the upper right corner of the RStudio console panel).
Every Shiny app has the same structure: an app.R
file that contains ui
and server
. You can create a Shiny app by making a new directory and saving an app.R
file inside it. It is recommended that each app will live in its own unique directory.
You can run a Shiny app by giving the name of its directory to the function runApp
. For example if your Shiny app is in a directory called my_app
, run it with the following code:
Note: runApp
is similar to read.csv
, read.table
, and many other functions in R. The first argument of runApp
is the filepath from your working directory to the app's directory. The code above assumes that the app directory is in your working directory. In this case, the filepath is just the name of the directory.
(In case you are wondering, the Hello Shiny app's files are saved in a special system directory called "01_hello"
. This directory is designed to work with the runExample ("01_hello")
call.)
Create a new directory named App-1
in your working directory. Then copy and paste the app.R
script above into your directory (the scripts from Hello Shiny). When you are finished the directory should look like this:
Launch your app by running runApp("App-1")
. Then click escape and make some changes to your app:
Change the title from “Hello Shiny!” to “Hello World!”.
Set the minimum value of the slider bar to 5.
Change the histogram border color from "white"
to "orange"
.
When you are ready, launch your app again. Your new app should match the image below. If it doesn't, or if you want to check your code, press the model answers button to reveal how we did these tasks.
By default, Shiny apps display in “normal” mode, like the app pictured above. Hello Shiny and the other built in examples display in “showcase mode”, a different mode that displays the app.R
script alongside the app.
If you would like your app to display in showcase mode, you can run runApp("App-1", display.mode = "showcase")
.
Change the title of your app and the slider bar values in the ui
object.
Use the server
function to change how your computer builds the histogram.
To relaunch your Shiny app:
Run runApp("App-1")
, or
Open the app.R
script in your RStudio editor. RStudio will recognize the Shiny script and provide a Run App button (at the top of the editor). Either click this button to launch your app or use the keyboard shortcut: Command+Shift+Enter (Control+Shift+Enter on Windows).
RStudio will launch the app in a new window by default, but you can also choose to have the app launch in a dedicated viewer pane, or in your external web browser. Make your selection by clicking the icon next to Run App.
To create your own Shiny app:
Make a directory named myapp/
for your app.
Save your app.R
script inside that directory.
Launch the app with runApp
or RStudio's keyboard shortcuts.
Exit the Shiny app by clicking escape.
You can create Shiny apps by copying and modifying existing Shiny apps. The Shiny gallery provides some good examples, or use the eleven pre-built Shiny examples listed below.
Each demonstrates a feature of Shiny apps. All Shiny example apps open in “showcase” mode (with the app.R
script in the display).
But why limit yourself to copying other apps? The next few lessons will show you how to build your own Shiny apps from scratch. You'll learn about each part of a Shiny app, and finish by deploying your own Shiny app online.
Now that you understand the structure of a Shiny app, it's time to build your first app from scratch.
This lesson will show you how to build a user interface for your app. You will learn how to lay out the user interface and then add text, images, and other HTML elements to your Shiny app.
We'll use the App-1
app you made in Lesson 1. To get started, open its app.R
file. Edit the script to match the one below:
This code is the bare minimum needed to create a Shiny app. The result is an empty app with a blank user interface, an appropriate starting point for this lesson.
Shiny uses the function fluidPage
to create a display that automatically adjusts to the dimensions of your user's browser window. You lay out the user interface of your app by placing elements in the fluidPage
function.
For example, the ui
function below creates a user interface that has a title panel and a sidebar layout, which includes a sidebar panel and a main panel. Note that these elements are placed within the fluidPage
function.
titlePanel
and sidebarLayout
are the two most popular elements to add to fluidPage
. They create a basic Shiny app with a sidebar.
sidebarLayout
always takes two arguments:
sidebarPanel
function output
mainPanel
function output
These functions place content in either the sidebar or the main panels.
The sidebar panel will appear on the left side of your app by default. You can move it to the right side by giving sidebarLayout
the optional argument position = "right"
.
titlePanel
and sidebarLayout
create a basic layout for your Shiny app, but you can also create more advanced layouts. You can use navbarPage
to give your app a multi-page user interface that includes a navigation bar. Or you can use fluidRow
and column
to build your layout up from a grid system. If you'd like to learn more about these advanced options, read the Shiny Application Layout Guide. We will stick with sidebarLayout
in this tutorial.
You can add content to your Shiny app by placing it inside a *Panel
function. For example, the apps above display a character string in each of their panels. The words “sidebar panel” appear in the sidebar panel, because we added the string to the sidebarPanel
function, e.g. sidebarPanel("sidebar panel")
. The same is true for the text in the title panel and the main panel.
To add more advanced content, use one of Shiny's HTML tag functions. These functions parallel common HTML5 tags. Let's try out a few of them.
shiny function | HTML5 equivalent | creates |
---|---|---|
p |
<p> |
A paragraph of text |
h1 |
<h1> |
A first level header |
h2 |
<h2> |
A second level header |
h3 |
<h3> |
A third level header |
h4 |
<h4> |
A fourth level header |
h5 |
<h5> |
A fifth level header |
h6 |
<h6> |
A sixth level header |
a |
<a> |
A hyper link |
br |
<br> |
A line break (e.g. a blank line) |
div |
<div> |
A division of text with a uniform style |
span |
<span> |
An in-line division of text with a uniform style |
pre |
<pre> |
Text ‘as is' in a fixed width font |
code |
<code> |
A formatted block of code |
img |
<img> |
An image |
strong |
<strong> |
Bold text |
em |
<em> |
Italicized text |
HTML |
Directly passes a character string as HTML code |
To create a header element:
select a header function (e.g., h1 or h5)
give it the text you want to see in the header
For example, you can create a first level header that says “My title” with h1("My title")
. If you run the command at the command line, you'll notice that it produces HTML code.
> library(shiny)
> h1("My title")
<h1>My title</h1>
To place the element in your app:
h1("My title")
as an argument to titlePanel
, sidebarPanel
, or mainPanel
The text will appear in the corresponding panel of your web page. You can place multiple elements in the same panel if you separate them with a comma.
Give this a try. The new script below uses all six levels of headers. Update your ui.R
to match the script and then relaunch your app. Remember to relaunch a Shiny app you may run runApp("App-1")
, click the Run App button, or use your keyboard shortcuts.
Now your app should look like this.
If George Lucas had a first app, it might look like this.
You can create this effect with align = "center"
, as in h6("Episode IV", align = "center")
. In general, any HTML tag attribute can be set as an argument in any Shiny tag function.
If you are unfamiliar with HTML tag attributes, you can look them up in one of the many free online HTML resources such as w3schools.
Here's the code for the ui
that made the Star Wars-inspired user interface:
Shiny offers many tag functions for formatting text. The easiest way to describe them is by running through an example.
Paste the ui
object below into your app.R
file and save it. If your Shiny app is still running, you can refresh your web page or preview window, and it will display the changes. If your app is closed, just relaunch it.
Compare the displayed app to your updated ui
object definition to discover how to format text in a Shiny app.
Images can enhance the appearance of your app and help your users understand the content. Shiny looks for the img
function to place image files in your app.
To insert an image, give the img
function the name of your image file as the src
argument (e.g., img(src = "my_image.png")
). You must spell out this argument since img
passes your input to an HTML tag, and src
is what the tag expects.
You can also include other HTML friendly parameters such as height and width. Note that height and width numbers will refer to pixels.
The img
function looks for your image file in a specific place. Your file must be in a folder named www
in the same directory as the app.R
script. Shiny treats this directory in a special way. Shiny will share any file placed here with your user's web browser, which makes www
a great place to put images, style sheets, and other things the browser will need to build the wep components of your Shiny app.
So if you want to use an image named rstudio.png, your App-1
directory should look like this one:
With this file arrangment, the ui
object below can create this app. Download rstudio.png here and try it out.
This lesson covers the most popular Shiny tag functions, but there are many more tag functions for you to use. You can learn about additional tag functions in Customize your UI with HTML and the Shiny HTML Tags Glossary.
You can use Shiny's layout, HTML, and img
functions to create very attractive and useful user interfaces. See how well you understand these functions by recreating the Shiny app pictured below. Use the examples in this tutorial to work on it and then test it out.
Our app.R
script is found under the Model Answer button, but don't just copy and paste it. Make sure you understand how the code works before moving on.
With your new skills, you can:
create a user interface with fluidPage
, titlePanel
and sidebarLayout
create an HTML element with one of Shiny's tag functions
set HTML tag attributes in the arguments of each tag function
add an element to your web page by passing it to titlePanel
, sidebarPanel
or mainPanel
add multiple elements to each panel by separating them with a comma
add images by placing your image in a folder labeled www
within your Shiny app directory and then calling the img
function
This lesson will show you how to add control widgets to your Shiny apps. What's a widget? A web element that your users can interact with. Widgets provide a way for your users to send messages to the Shiny app.
Shiny widgets collect a value from your user. When a user changes the widget, the value will change as well. This sets up opportunities that we'll explore in Lesson 4.
Shiny comes with a family of pre-built widgets, each created with a transparently named R function. For example, Shiny provides a function named actionButton
that creates an Action Button and a function named sliderInput
that creates a slider bar.
The standard Shiny widgets are:
function | widget |
---|---|
actionButton |
Action Button |
checkboxGroupInput |
A group of check boxes |
checkboxInput |
A single check box |
dateInput |
A calendar to aid date selection |
dateRangeInput |
A pair of calendars for selecting a date range |
fileInput |
A file upload control wizard |
helpText |
Help text that can be added to an input form |
numericInput |
A field to enter numbers |
radioButtons |
A set of radio buttons |
selectInput |
A box with choices to select from |
sliderInput |
A slider bar |
submitButton |
A submit button |
textInput |
A field to enter text |
Some of these widgets are built using the Twitter Bootstrap project, a popular open source framework for building user interfaces.
You can add widgets to your web page in the same way that you added other types of HTML content in Lesson 2. To add a widget to your app, place a widget function in sidebarPanel
or mainPanel
in your ui
object.
Each widget function requires several arguments. The first two arguments for each widget are
a name for the widget: The user will not see this name, but you can use it to access the widget's value. The name should be a character string.
a label: This label will appear with the widget in your app. It should be a character string, but it can be an empty string ""
.
In this example, the name is “action” and the label is “Action”: actionButton("action", label = "Action")
The remaining arguments vary from widget to widget, depending on what the widget needs to do its job. They include things like initial values, ranges, and increments. You can find the exact arguments needed by a widget on the widget function's help page, (e.g., ?selectInput
).
The app.R
script below makes the app pictured above. Change your own App-1/app.R
script to match it, and then launch the app (runApp("App-1")
, select Run App, or use shortcuts).
Play with each widget to get a feel for what it does. Experiment with changing the values of the widget functions and observe the effects. If you are interested in the layout scheme for this Shiny app, read the description in the application layout guide. This lesson will not cover this slightly more complicated layout scheme, but it is interesting to note what it does.
Rewrite your ui
to create the user interface displayed below. Notice that this Shiny app uses a basic Shiny layout (no columns) and contains three of the widgets pictured above. The other values of the select box are shown below the image of the app.
Be sure your ui
is identical to the one displayed below before you move on. You will use the script in Lesson 4 and Lesson 5, as part of an app that visualizes census data.
In particular, make sure that your select box widget is named “var”, and your slider widget is named “range”.
Also notice that the slider widget has two values, not one.
It is easy to add fully functional widgets to your Shiny app.
Shiny provides a family of functions to create these widgets.
Each function requires a name and a label.
Some widgets need specific instructions to do their jobs.
You add widgets to your Shiny app just like you added other types of HTML content (see Lesson 2)
The Shiny Widgets Gallery provides templates that you can use to quickly add widgets to your Shiny apps.
To use a template, visit the gallery. The gallery displays each of Shiny's widgets, and demonstrates how the widgets' values change in response to your input.
Select the widget that you want and click the “See Code” button below the widget. The gallery will take you to an example app that describes the widget. To use the widget, copy and paste the code in the example's app.R
file to your app.R
file.
In Lesson 4, you will learn how to connect widgets to reactive output, objects that update themselves whenever your user changes a widget.
Time to give your Shiny app a “live” quality! This lesson will teach you how to build reactive output to displays in your Shiny app. Reactive output automatically responds when your user toggles a widget.
By the end of this lesson, you'll know how to make a simple Shiny app with two reactive lines of text. Each line will display the values of a widget based on your user's input.
This new Shiny app will need its own, new directory. Create a folder in your working directory named census-app
. This is where we'll save the app.R
file that you make in this lesson.
You can create reactive output with a two step process.
Shiny provides a family of functions that turn R objects into output for your user interface. Each function creates a specific type of output.
Output function | Creates |
---|---|
dataTableOutput |
DataTable |
htmlOutput |
raw HTML |
imageOutput |
image |
plotOutput |
plot |
tableOutput |
table |
textOutput |
text |
uiOutput |
raw HTML |
verbatimTextOutput |
text |
You can add output to the user interface in the same way that you added HTML elements and widgets. Place the output function inside sidebarPanel
or mainPanel
in the ui
.
For example, the ui
object below uses textOutput
to add a reactive line of text to the main panel of the Shiny app pictured above.
Notice that textOutput
takes an argument, the character string "selected_var"
. Each of the *Output
functions require a single argument: a character string that Shiny will use as the name of your reactive element. Your users will not see this name, but you will use it later.
Placing a function in ui
tells Shiny where to display your object. Next, you need to tell Shiny how to build the object.
We do this by providing the R code that builds the object in the server
function.
The server
function plays a special role in the Shiny process; it builds a list-like object named output
that contains all of the code needed to update the R objects in your app. Each R object needs to have its own entry in the list.
You can create an entry by defining a new element for output
within the server
function, like below. The element name should match the name of the reactive element that you created in the ui
.
In the server
function below, output$selected_var
matches textOutput("selected_var")
in your ui
.
You do not need to explicitly state in the server
function to return output
in its last line of code. R will automatically update output
through reference class semantics.
Each entry to output
should contain the output of one of Shiny's render*
functions. These functions capture an R expression and do some light pre-processing on the expression. Use the render*
function that corrresponds to the type of reactive object you are making.
render function | creates |
---|---|
renderDataTable |
DataTable |
renderImage |
images (saved as a link to a source file) |
renderPlot |
plots |
renderPrint |
any printed output |
renderTable |
data frame, matrix, other table like structures |
renderText |
character strings |
renderUI |
a Shiny tag object or HTML |
Each render*
function takes a single argument: an R expression surrounded by braces, {}
. The expression can be one simple line of text, or it can involve many lines of code, as if it were a complicated function call.
Think of this R expression as a set of instructions that you give Shiny to store for later. Shiny will run the instructions when you first launch your app, and then Shiny will re-run the instructions every time it needs to update your object.
For this to work, your expression should return the object you have in mind (a piece of text, a plot, a data frame, etc.). You will get an error if the expression does not return an object, or if it returns the wrong type of object.
If you run the app with the server
function above, it will display “You have selected this” in the main panel. However, the text will not be reactive. It will not change even if you manipulate the widgets of your app.
You can make the text reactive by asking Shiny to call a widget value when it builds the text. Let's look at how to do this.
Take a look at the first line of code in the server
function. Do you notice that the server
function mentions two arguments, input
and output
? You already saw that output
is a list-like object that stores instructions for building the R objects in your app.
input
is a second list-like object. It stores the current values of all of the widgets in your app. These values will be saved under the names that you gave the widgets in your ui
.
So for example, our app has two widgets, one named "var"
and one named "range"
(you gave the widgets these names in Lesson 3). The values of "var"
and "range"
will be saved in input
as input$var
and input$range
. Since the slider widget has two values (a min and a max), input$range
will contain a vector of length two.
Shiny will automatically make an object reactive if the object uses an input
value. For example, the server
function below creates a reactive line of text by calling the value of the select box widget to build the text.
Shiny tracks which outputs depend on which widgets. When a user changes a widget, Shiny will rebuild all of the outputs that depend on the widget, using the new value of the widget as it goes. As a result, the rebuilt objects will be completely up-to-date.
This is how you create reactivity with Shiny, by connecting the values of input
to the objects in output
. Shiny takes care of all of the other details.
When you are ready, update your server
and ui
functions to match those above. Then launch your Shiny app by running runApp("census-app", display.mode = "showcase")
at the command line. Your app should look like the app below, and your statement should update instantly as you change the select box widget.
Watch the server
portion of the script. When Shiny rebuilds an output, it highlights the code it is running. This temporary highlighting can help you see how Shiny generates reactive output.
Add a second line of reactive text to the main panel of your Shiny app. This line should display “You have chosen a range that goes from something to something”, and each something should show the current minimum (min) or maximum (max) value of the slider widget.
Don't forget to update both your ui
object and your server
function.
Add the second line of text in the same way that you added the first one. Use textOutput
in ui
to place the second line of text in the main panel. Use renderText
in server
to tell Shiny how to build the text. You'll need to use the same name to refer to the text in both scripts (e.g., "min_max"
).
Your text should use both the slider's min value (saved as input$range[1]
) and its max value (saved as input$range[2]
).
Remember that your text will be reactive as long as you connect input
values to output
objects. Shiny creates reactivity automatically when it recognizes these connections.
In this lesson, you created your first reactive Shiny app. Along the way, you learned to
*Output
function in the ui
to place reactive objects in your Shiny app,render*
function in the server
to tell Shiny how to build your objects,{}
, in each render*
function,render*
expressions in the output
list, with one entry for each reactive object in your app, andinput
value in a render*
expression.If you follow these rules, Shiny will automatically make your objects reactive.
In Lesson 5 you will create a more sophisticated reactive app that relies on R scripts and external data.
This lesson will show you how to load data, R Scripts, and packages to use in your Shiny apps. Along the way, you will build a sophisticated app that visualizes US Census data.
counties.rds
is a dataset of demographic data for each county in the United States, collected with the UScensus2010
R package. You can download it here.
Once you have the file,
data
in your census-app
directory.counties.rds
into the data
folder.When you're done, your census-app
folder should look like this.
The dataset in counties.rds
contains
helpers.R
is an R script that can help you make choropleth maps, like the ones pictured above. A choropleth map is a map that uses color to display the regional variation of a variable. In our case, helpers.R
will create percent_map
, a function designed to map the data in counties.rds
. You can download helpers.R
here.
helpers.R
uses the maps
and mapproj
packages in R. If you've never installed these packages before, you'll need to do so before you make this app. Run
Save helpers.R
inside your census-app
directory, like below.
The percent_map
function in helpers.R
takes five arguments:
Argument | Input |
---|---|
var |
a column vector from the counties.rds dataset |
color |
any character string you see in the output of colors() |
legend.title |
A character string to use as the title of the plot's legend |
max |
A parameter for controlling shade range (defaults to 100) |
min |
A parameter for controlling shade range (defaults to 0) |
You can use percent_map
at the command line to plot the counties data as a choropleth map, like this.
Note: The code above assumes that census-app
is a sub-directory in your working directory. Make certain to set your working directory as the parent directory for census-app
. To change your working directory location, click on Session > Set Working Directory > Choose Directory… in the RStudio menu bar.
percent_map
plots the counties data as a choropleth map. Here it will plot the percent of white residents in the counties in the color dark green.
Take a look at the above code. To use percent_map
, we first ran helpers.R
with the source
function, and then loaded counties.rds
with the readRDS
function. We also ran library(maps)
and library(mapproj)
.
You will need to ask Shiny to call the same functions before it uses percent_map
in your app, but how you write these functions will change. Both source
and readRDS
require a file path, and file paths do not behave the same way in a Shiny app as they do at the command line.
When Shiny runs the commands in server.R
, it will treat all file paths as if they begin in the same directory as server.R
. In other words, the directory that you save server.R
in will become the working directory of your Shiny app.
Since you saved helpers.R
in the same directory as server.R
, you can ask Shiny to load it with
Since you saved counties.rds
in a sub-directory (named data) of the directory that server.R
is in, you can load it with.
You can load the maps
and mapproj
packages in the normal way with
which does not require a file path.
Shiny will execute all of these commands if you place them in your app.R
script. However, where you place them will determine how many times they are run (or re-run), which will in turn affect the performance of your app, since Shiny will run some sections your app.R
script more often than others.
Shiny will run the whole script the first time you call runApp
. This causes Shiny to execute the server
function.
Shiny saves the server
function until a new user arrives. Each time a new user visits your app, Shiny runs the server
function again, one time. The function helps Shiny build a distinct set of reactive objects for each user.
As users interact with the widgets and change their values, Shiny will re-run the R expressions assigned to each reactive object that depend on a widget whose value was changed. If your user is very active, these expressions may be re-run many, many times a second.
Here's what we've learned so far:
shinyApp
function is run once, when you launch your appserver
function is run once each time a user visits your apprender*
functions are run many times. Shiny runs them once each time a user change the value of a widget.How can you use this information?
Source scripts, load libraries, and read data sets at the beginning of app.R
outside of the server
function. Shiny will only run this code once, which is all you need to set your server up to run the R expressions contained in server
.
Define user specific objects inside server
function, but outside of any render*
calls. These would be objects that you think each user will need their own personal copy of. For example, an object that records the user's session information. This code will be run once per user.
Only place code that Shiny must rerun to build an object inside of a render*
function. Shiny will rerun all of the code in a render*
chunk each time a user changes a widget mentioned in the chunk. This can be quite often.
You should generally avoid placing code inside a render
function that does not need to be there. Doing so will slow down the entire app.
Copy and paste the following app.R
file to your census-app
directory. Then add
to your app.R
script. Be sure to place the commands in an efficient location.
Note: This is the first of two steps that will complete your app. Choose the best place to insert the code above, but do not try to run the app. Your app will return an error until you replace # some arguments
with real code in Your Turn 2.
Since your app only needs to load helpers.R
and counties.rds
once, they should go outside of the ui
and server
functions. This is also a good place to load the maps
library (which percent_map
uses).
You may wonder, “Won't each user need their own copy of counties
and percent_map
?” (which would imply that the code should go inside of the server
function). No, each user will not.
Keep in mind that your user's computer won't run any of the R code in your Shiny app. In fact, their computer won't even see the R code. The computer that you use as a server will run all of the R code necessary for all of your users. It will send the results over to your users as HTML elements.
Your server can rely on a single global copy of counties.rds
and percent_map
to do all of the R execution necessary for all of the users. You only need to build a separate object for each user if the objects will have different values for each of your users.
The census visualization app has one reactive object, a plot named "map"
. The plot is built with the percent_map
function, which takes five arguments.
var
, color
, and legend.title
, depend on the value of the select box widget.max
and min
, should be the max and min values of the slider bar widget.The server
function below shows one way to craft reactive arguments for percent_map
. R's switch
function can transform the output of a select box widget to whatever you like. However, the script is incomplete. It does not provide values for color
, legend.title
, max
, or min
. Note: the script will not run as is. You will need to finish the script before you run it, which is the task of Your Turn 2.
Complete the code to build a working census visualization app.
When you're ready to deploy your app, save your app.R
file and run runApp("census-app")
. If everything works, your app should look like the picture below.
You'll need to decide
percent_map
, andRemember, you'll want the argument values to switch whenever a user changes the associated widget. When you are finished, or if you get stuck, read on below for a model answer.
A more concise version of the server
function:
You can create more complicated Shiny apps by loading R Scripts, packages, and data sets.
Keep in mind:
app.R
appears in will become the working directory of the Shiny appapp.R
, before the server
function, only once during the life of the app.server
function multiple times, which can slow down the app.You also learned that switch
is a useful companion to multiple choice Shiny widgets. Use switch
to change the values of a widget into R expressions.
As your apps become more complex, they can become inefficient and slow. Lesson 6 will show you how to build fast, modular apps with reactive expressions.
Shiny apps wow your users by running fast, instantly fast. But what if your app needs to do a lot of slow computation?
This lesson will show you how to streamline your Shiny apps with reactive expressions. Reactive expressions let you control which parts of your app update when, which prevents unnecessary computation that can slow down your app.
To get started:
stockVis
in your working directory.stockVis
: app.R and helpers.R.runApp("stockVis")
StockVis use R's quantmod
package, so you'll need to install quantmod
with install.packages("quantmod")
if you do not already have it.
The stockVis app looks up stock prices by ticker symbol and displays the results as a line chart. The app lets you
Note that the “Adjust prices for inflation” check box doesn't work yet. One of our tasks in this lesson is to fix this check box.
By default, stockVis displays the SPY ticker (an index of the entire S&P 500). To look up a different stock, type in a stock symbol that Google finance will recognize. You can look up Google's stock symbols here. Some common symbols are GOOG (Google), AAPL (Apple), and GS (Goldman Sachs).
stockVis relies heavily on two functions from the quantmod
package:
getSymbols
to download financial data straight into R from websites like Google finance and the Federal Reserve Bank of St. Louis.chartSeries
to display prices in an attractive chart.stockVis also relies on an R script named helpers.R
, which contains a function that adjusts stock prices for inflation.
The stockVis app uses a few new widgets.
dateRangeInput
, andcheckboxInput
. Check box widgets are very simple. They return a TRUE
when the check box is checked, and a FALSE
when the check box is not checked.The check boxes are named log
and adjust
in the ui
object, which means you can look them up as input$log
and input$adjust
in the server
function. If you'd like to review how to use widgets and their values, check out Lesson 3 and Lesson 4.
The stockVis app has a problem.
Examine what will happen when you click “Plot y axis on the log scale.” The value of input$log
will change, which will cause the entire expression in renderPlot
to re-run:
Each time renderPlot
re-runs
getSymbols
, andThis is not good, because you do not need to re-fetch the data to re-draw the plot. In fact, Google finance will cut you off if you re-fetch your data too often (because you begin to look like a bot). But more importantly, re-running getSymbols
is unnecessary work, which can slow down your app and consume server bandwidth.
You can limit what gets re-run during a reaction with reactive expressions.
A reactive expression is an R expression that uses widget input and returns a value. The reactive expression will update this value whenever the original widget changes.
To create a reactive expression use the reactive
function, which takes an R expression surrounded by braces (just like the render*
functions).
For example, here's a reactive expression that uses the widgets of stockVis to fetch data from Google.
When you run the expression, it will run getSymbols
and return the results, a data frame of price data. You can use the expression to access price data in renderPlot
by calling dataInput()
.
Reactive expressions are a bit smarter than regular R functions. They cache their values and know when their values have become outdated. What does this mean? The first time that you run a reactive expression, the expression will save its result in your computer's memory. The next time you call the reactive expression, it can return this saved result without doing any computation (which will make your app faster).
The reactive expression will only return the saved result if it knows that the result is up-to-date. If the reactive expression has learned that the result is obsolete (because a widget has changed), the expression will recalculate the result. It then returns the new result and saves a new copy. The reactive expression will use this new copy until it too becomes out of date.
Let's summarize this behavior:
A reactive expression saves its result the first time you run it.
The next time the reactive expression is called, it checks if the saved value has become out of date (i.e., whether the widgets it depends on have changed).
If the value is out of date, the reactive object will recalculate it (and then save the new result).
If the value is up-to-date, the reactive expression will return the saved value without doing any computation.
You can use this behavior to prevent Shiny from re-running code unnecessarily. Consider how a reactive expression will work in the new stockVis app below.
When you click “Plot y axis on the log scale”, input$log
will change and renderPlot
will re-execute. Now
renderPlot
will call dataInput()
dataInput
will check that the dates
and symb
widgets have not changeddataInput
will return its saved data set of stock prices without re-fetching data from GooglerenderPlot
will re-draw the chart with the correct axis.What if your user changes the stock symbol in the symb
widget?
This will make the plot drawn by renderPlot
out of date, but renderPlot
no longer calls input$symb
. Will Shiny know that input$symb
has made plot out of date?
Yes, Shiny will know and will redraw the plot. Shiny keeps track of which reactive expressions an output
object depends on, as well as which widget inputs. Shiny will automatically re-build an object if
input
value in the objects's render*
function changes, orrender*
function becomes obsoleteThink of reactive expressions as links in a chain that connect input
values to output
objects. The objects in output
will respond to changes made anywhere downstream in the chain. (You can fashion a long chain because reactive expressions can call other reactive expressions.)
Only call a reactive expression from within a reactive
or a render*
function. Why? Only these R functions are equipped to deal with reactive output, which can change without warning. In fact, Shiny will prevent you from calling reactive expressions outside of these functions.
Time to fix the broken check box for “Adjust prices for inflation.” Your user should be able to toggle between prices adjusted for inflation and prices that have not been adjusted.
The adjust
function in helpers.R
uses the Consumer Price Index data provided by the Federal Reserve Bank of St. Louis to transform historical prices into present day values. But how can you implement this in the app?
Here's one solution below, but it is not ideal. Can you spot why? Once again it has to do with input$log
.
adjust
is called inside renderPlot
. If the adjust box is checked, the app will readjust all of the prices each time you switch from a normal y scale to a logged y scale. This readjustment is unnecessary work.
Fix this problem by adding a new reactive expression to the app. The reactive expression should take the value of dataInput
and return an adjusted (or not adjusted) copy of the data.
When you think you have it, compare your solution to the model answer below. Make sure you understand what calculations will happen and what calculations will not happen in your app when your user clicks “Plot y axis on the log scale”.
Now you have isolated each input in its own reactive expression or render*
function. If an input changes, only out of date expressions will re-run.
Here's an example of the flow:
renderPlot
re-runs.renderPlot
calls finalInput
.finalInput
checks with dataInput
and input$adjust
.finalInput
returns its saved value.finalInput
calculates a new value with the current inputs. It will pass the new value to renderPlot
and store the new value for future queries.You can make your apps faster by modularizing your code with reactive expressions.
input
values, or values from other reactive expressions, and returns a new valuereactive({ })
()
render*
functionsY
You can now build a useful Shiny app, but can you share it with others? This lesson will show you several ways to share your Shiny apps.
When it comes to sharing Shiny apps, you have two basic options:
Share your Shiny app as R scripts. This is the simplest way to share an app, but it works only if your users have R on their own computer (and know how to use it). Users can use these scripts to launch the app from their own R session, just like you've been launching the apps so far in this tutorial.
Share your Shiny app as a web page. This is definitely the most user friendly way to share a Shiny app. Your users can navigate to your app through the internet with a web browser. They will find your app fully rendered, up to date, and ready to go.
Anyone with R can run your Shiny app. They will need a copy of your app.R
file, as well as any supplementary materials used in your app (e.g., www
folders or helpers.R
files).
To send your files to another user, email the files (perhaps in a zip file) or host the files online.
Your user can place the files into an app directory in their working directory. They can launch the app in R with the same commands you used on your computer.
Shiny has three built in commands that make it easy to use files that are hosted online: runUrl
, runGitHub
, and runGist
.
runUrl
will download and launch a Shiny app straight from a weblink.
To use runURL
:
If you don't have your own web page to host the files at, you can host your the files for free at www.github.com.
GitHub is a popular project hosting site for R developers since it does more than just host files. GitHub provides many features to support collaboration, such as issue trackers, wikis, and close integration with the git version control system. To use GitHub, you'll need to sign up (it's free) and choose a user name.
To share an app through GitHub, create a project repository on GitHub. Then store your app.R
file in the repository, along with any supplementary files that the app uses.
Your users can launch your app by running:
If you want an anonymous way to post files online, GitHub offers a pasteboard service for sharing files at gist.github.com. You don't need to sign up for a GitHub account to use this service. Even if you have a GitHub account, gist can be a simple, quick way to share Shiny projects.
To share your app as a gist:
app.R
files to the gist web page.Once you've made a gist, your users can launch the app with runGist("<gist number>")
where "<gist number>"
is the number that appears at the end of your Gist's web address.
Here is an example of an app hosted as a gist. You could launch this app with:
All of the above methods share the same limitation. They require your user to have R and Shiny installed on their computer.
However, Shiny creates the perfect opportunity to share output with people who do not have R (and have no intention of getting it). Your Shiny app happens to be one of the most widely used communication tools in the world: a web page. If you host the app at its own URL, users can visit the app (and not need to worry about the code that generates it).
If you are familiar with web hosting or have access to an IT department, you can host your Shiny apps yourself.
If you'd prefer an easier experience or need support, RStudio offers four ways to host your Shiny app as a web page:
The easiest way to turn your Shiny app into a web page is to use shinyapps.io, RStudio's hosting service for Shiny apps.
shinyapps.io lets you upload your app straight from your R session to a server hosted by RStudio. You have complete control over your app including server administration tools. You can find out more about shinyapps.io by visiting shinyapps.io.
Shiny Server is a companion program to Shiny that builds a web server designed to host Shiny apps. It's free, open source, and available from GitHub.
Shiny Server is a server program that Linux servers can run to host a Shiny app as a web page. To use Shiny Server, you'll need a Linux server that has explicit support for Ubuntu 12.04 or greater (64 bit) and CentOS/RHEL 5 (64 bit). If you are not using an explicitly supported distribution, you can still use Shiny Server by building it from source.
You can host multiple Shiny applications on multiple web pages with the same Shiny Server, and you can deploy the apps from behind a firewall.
To see detailed instructions for installing and configuring a Shiny Server, visit the Shiny Server guide.
Shiny Server will get your app to the web and take care of all of your Shiny publishing needs. However, if you use Shiny in a for-profit setting, you may want to give yourself the server tools that come with most paid server programs, such as
If so, check out Shiny Server Pro, RStudio's paid professional version of Shiny Server.
RStudio Connect is a new publishing platform for the work your teams create in R. Share Shiny applications, R Markdown reports, dashboards, plots, and more in one convenient place. With RStudio Connect, you can publish from the RStudio IDE with the push of a button and schedule execution of reports and flexible security policies.
If you'd like to learn more about RStudio Connect and the features it offers, see here.
Shiny apps are easy to share. You can share your app as a couple of R scripts, or as a fully functioning web app with its own URL. Each method has its own advantages.
You learned:
runUrl
, runGitHub
, and runGist
make it simple to share and retrieve Shiny files from web links.Congratulations. You've worked through the entire Shiny development process. You can build a sophisticated, reactive app, deploy it, and share it with others. Users can interact with your data and follow your stories in a new way.
The next step is to practice, and then explore the advanced features of Shiny.
The Shiny Dev Center can help you along the way. It hosts a gallery of inspiring apps, along with the code that makes the apps.
The Shiny Dev Center also includes an articles section for continuing education. Each article examines an intermediate to advanced Shiny topic in depth.
You now know enough to build your own Shiny apps. See what you can do!
UI LayoutFunctions for laying out the user interface for your application. |
|
absolutePanel (fixedPanel) |
Panel with absolute positioning
|
bootstrapPage (basicPage) |
Create a Bootstrap page
|
column |
Create a column within a UI definition
|
conditionalPanel |
Conditional Panel
|
fillPage |
Create a page that fills the window
|
fillRow (fillCol) |
Flex Box-based row/column layouts
|
fixedPage (fixedRow) |
Create a page with a fixed layout
|
fluidPage (fluidRow) |
Create a page with fluid layout
|
headerPanel |
Create a header panel
|
helpText |
Create a help text element
|
icon |
Create an icon
|
mainPanel |
Create a main panel
|
navbarPage (navbarMenu) |
Create a page with a top level navigation bar
|
navlistPanel |
Create a navigation list panel
|
pageWithSidebar |
Create a page with a sidebar
|
sidebarLayout |
Layout a sidebar and main area
|
sidebarPanel |
Create a sidebar panel
|
tabPanel |
Create a tab panel
|
tabsetPanel |
Create a tabset panel
|
titlePanel |
Create a panel containing an application title.
|
inputPanel |
Input panel
|
flowLayout |
Flow layout
|
splitLayout |
Split layout
|
verticalLayout |
Lay out UI elements vertically
|
wellPanel |
Create a well panel
|
withMathJax |
Load the MathJax library and typeset math expressions
|
UI InputsFunctions for creating user interface elements that prompt the user for input values or interaction. |
|
actionButton (actionLink) |
Action button/link
|
checkboxGroupInput |
Checkbox Group Input Control
|
checkboxInput |
Checkbox Input Control
|
dateInput |
Create date input
|
dateRangeInput |
Create date range input
|
fileInput |
File Upload Control
|
numericInput |
Create a numeric input control
|
radioButtons |
Create radio buttons
|
selectInput (selectizeInput) |
Create a select list input control
|
sliderInput (animationOptions) |
Slider Input Widget
|
submitButton |
Create a submit button
|
textInput |
Create a text input control
|
textAreaInput |
Create a textarea input control
|
passwordInput |
Create a password input control
|
modalButton |
Create a button for a modal dialog
|
updateActionButton |
Change the label or icon of an action button on the client
|
updateCheckboxGroupInput |
Change the value of a checkbox group input on the client
|
updateCheckboxInput |
Change the value of a checkbox input on the client
|
updateDateInput |
Change the value of a date input on the client
|
updateDateRangeInput |
Change the start and end values of a date range input on the client
|
updateNumericInput |
Change the value of a number input on the client
|
updateRadioButtons |
Change the value of a radio input on the client
|
updateSelectInput (updateSelectizeInput) |
Change the value of a select input on the client
|
updateSliderInput |
Change the value of a slider input on the client
|
updateTabsetPanel (updateNavbarPage, updateNavlistPanel) |
Change the selected tab on the client
|
insertTab (prependTab, appendTab, removeTab) |
Dynamically insert/remove a tabPanel
|
showTab (hideTab) |
Dynamically hide/show a tabPanel
|
updateTextInput |
Change the value of a text input on the client
|
updateTextAreaInput |
Change the value of a textarea input on the client
|
updateQueryString |
Update URL in browser's location bar
|
getQueryString (getUrlHash) |
Get the query string / hash component from the URL
|
UI OutputsFunctions for creating user interface elements that, in conjunction with rendering functions, display different kinds of output from your application. |
|
htmlOutput (uiOutput) |
Create an HTML output element
|
plotOutput (imageOutput) |
Create an plot or image output element
|
outputOptions |
Set options for an output object.
|
tableOutput (dataTableOutput) |
Create a table output element
|
textOutput |
Create a text output element
|
verbatimTextOutput |
Create a verbatim text output element
|
downloadButton (downloadLink) |
Create a download button or link
|
Progress |
Reporting progress (object-oriented API)
|
withProgress (setProgress, incProgress) |
Reporting progress (functional API)
|
modalDialog |
Create a modal dialog UI
|
urlModal |
Generate a modal dialog that displays a URL
|
showModal (removeModal) |
Show or remove a modal dialog
|
showNotification (removeNotification) |
Show or remove a notification
|
Interface builder functionsA sub-library for writing HTML using R functions. These functions form the foundation on which the higher level user interface functions are built, and can also be used in your Shiny UI to provide custom HTML, CSS, and JavaScript. |
|
builder (a, br, code, div, em, h1, h2, h3, h4, h5, h6, hr, img, p, pre, span, strong, tags) |
HTML Builder Functions
|
HTML |
Mark Characters as HTML
|
include (includeCSS, includeHTML, includeMarkdown, includeScript, includeText) |
Include Content From a File
|
singleton (is.singleton) |
Include content only once
|
tag (tagAppendAttributes, tagAppendChild, tagAppendChildren, tagList, tagSetChildren) |
HTML Tag Object
|
validateCssUnit |
Validate proper CSS formatting of a unit
|
withTags |
Evaluate an expression using
tags |
htmlTemplate |
Process an HTML template
|
bootstrapLib |
Bootstrap libraries
|
suppressDependencies |
Suppress web dependencies
|
insertUI |
Insert UI objects
|
removeUI |
Remove UI objects
|
Rendering functionsFunctions that you use in your application's server side code, assigning them to outputs that appear in your user interface. |
|
renderPlot |
Plot Output
|
renderText |
Text Output
|
renderPrint |
Printable Output
|
renderDataTable |
Table output with the JavaScript library DataTables
|
renderImage |
Image file output
|
renderTable |
Table Output
|
renderUI |
UI Output
|
downloadHandler |
File Downloads
|
reactivePlot |
Plot output (deprecated)
|
reactivePrint |
Print output (deprecated)
|
reactiveTable |
Table output (deprecated)
|
reactiveText |
Text output (deprecated)
|
reactiveUI |
UI output (deprecated)
|
Reactive programmingA sub-library that provides reactive programming facilities for R. |
|
reactive (is.reactive) |
Create a reactive expression
|
observe |
Create a reactive observer
|
observeEvent (eventReactive) |
Event handler
|
reactiveVal |
Create a (single) reactive value
|
reactiveValues |
Create an object for storing reactive values
|
reactiveValuesToList |
Convert a reactivevalues object to a list
|
is.reactivevalues |
Checks whether an object is a reactivevalues object
|
isolate |
Create a non-reactive scope for an expression
|
invalidateLater |
Scheduled Invalidation
|
debounce (throttle) |
Slow down a reactive expression with debounce/throttle
|
showReactLog |
Reactive Log Visualizer
|
makeReactiveBinding |
Make a reactive variable
|
reactiveFileReader |
Reactive file reader
|
reactivePoll |
Reactive polling
|
reactiveTimer |
Timer
|
domains (getDefaultReactiveDomain, withReactiveDomain, onReactiveDomainEnded) |
Reactive domains
|
BoilerplateFunctions that are required boilerplate in ui.R and server.R. |
|
shinyUI |
Create a Shiny UI handler
|
shinyServer |
Define Server Functionality
|
RunningFunctions that are used to run or stop Shiny applications. |
|
runApp |
Run Shiny Application
|
runGadget |
Run a gadget
|
runExample |
Run Shiny Example Applications
|
runGadget |
Run a gadget
|
runUrl (runGist, runGitHub) |
Run a Shiny application from a URL
|
stopApp |
Stop the currently running Shiny app
|
viewer (paneViewer, dialogViewer, browserViewer) |
Viewer options
|
isRunning |
Check whether a Shiny application is running
|
Bookmarking stateFunctions that are used for bookmarking and restoring state. |
|
bookmarkButton |
Create a button for bookmarking/sharing
|
enableBookmarking |
Enable bookmarking for a Shiny application
|
setBookmarkExclude |
Exclude inputs from bookmarking
|
showBookmarkUrlModal |
Display a modal dialog for bookmarking
|
onBookmark (onBookmarked, onRestore, onRestored) |
Add callbacks for Shiny session bookmarking events
|
Extending ShinyFunctions that are intended to be called by third-party packages that extend Shiny. |
|
createWebDependency |
Create a web dependency
|
addResourcePath |
Resource Publishing
|
registerInputHandler |
Register an Input Handler
|
removeInputHandler |
Deregister an Input Handler
|
markRenderFunction |
Mark a function as a render function
|
Utility functionsMiscellaneous utilities that may be useful to advanced users or when extending Shiny. |
|
req (isTruthy) |
Check for required values
|
validate (need) |
Validate input values and other conditions
|
session |
Session object
|
safeError |
Declare an error safe for the user to see
|
onFlush (onFlushed, onSessionEnded) |
Add callbacks for Shiny session events
|
restoreInput |
Restore an input value
|
applyInputHandlers |
Apply input handlers to raw input values
|
exprToFunction |
Convert an expression to a function
|
installExprFunction |
Install an expression as a function
|
parseQueryString |
Parse a GET query string from a URL
|
plotPNG |
Run a plotting function and save the output as a PNG
|
exportTestValues |
Register expressions for export in test mode
|
setSerializer |
Add a function for serializing an input before bookmarking application state
|
snapshotExclude |
Mark an output to be excluded from test snapshots
|
snapshotPreprocessInput |
Add a function for preprocessing an input before taking a test snapshot
|
snapshotPreprocessOutput |
Add a function for preprocessing an output before taking a test snapshot
|
markOutputAttrs |
Mark a render function with attributes that will be used by the output
|
repeatable |
Make a random number generator repeatable
|
shinyDeprecated |
Print message for deprecated functions in Shiny
|
serverInfo |
Collect information about the Shiny Server environment
|
shiny-options |
Global options for Shiny
|
onStop |
Run code after an application or session ends
|
Plot interactionFunctions related to interactive plots |
|
brushedPoints |
Find rows of data that are selected by a brush
|
brushOpts |
Create an object representing brushing options
|
clickOpts |
Create an object representing click options
|
dblclickOpts |
Create an object representing double-click options
|
hoverOpts |
Create an object representing hover options
|
nearPoints |
Find rows of data that are near a click/hover/double-click
|
Functions for modularizing Shiny apps |
|
NS (ns.sep) |
Namespaced IDs for inputs/outputs
|
callModule |
Invoke a Shiny module
|
EmbeddingFunctions that are intended for third-party packages that embed Shiny applications. |
|
shinyApp (shinyAppDir, shinyAppFile, as.shiny.appobj, as.shiny.appobj.shiny.appobj, as.shiny.appobj.list, as.shiny.appobj.character, is.shiny.appobj, print.shiny.appobj, as.tags.shiny.appobj) |
Create a Shiny app object
|
maskReactiveContext |
Evaluate an expression without a reactive context
|
Other |
|
freezeReactiveVal (freezeReactiveValue) |
Freeze a reactive value
|
getShinyOption (shinyOptions) |
Get or set Shiny options
|
knit_print.html (knit_print.shiny.tag, knit_print.shiny.tag.list) |
Knitr S3 methods
|
knitr_methods (knit_print.shiny.appobj, knit_print.shiny.render.function, knit_print.reactive) |
Knitr S3 methods
|
shiny-package (shiny) |
Web Application Framework for R
|